home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 45
/
Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso
/
Aminet
/
gfx
/
x11
/
x3270_3_2_16.lha
/
amiga_src
/
ft_dft.c
< prev
next >
Wrap
C/C++ Source or Header
|
2009-02-22
|
12KB
|
526 lines
/*
* Modifications Copyright 1996, 1999, 2000 by Paul Mattes.
* Copyright Octover 1995 by Dick Altenbern.
* Based in part on code Copyright 1993, 1994, 1995 by Paul Mattes.
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation.
*/
/*
* tc_dft.c
* File transfer: DFT-style data processing functions
*/
#include "globals.h"
#if defined(X3270_FT) /*[*/
#include "appres.h"
#include "3270ds.h"
#include "ft_dft_ds.h"
#include "actionsc.h"
#include "kybdc.h"
#include "ft_dftc.h"
#include "ftc.h"
#include "tablesc.h"
#include "telnetc.h"
#include "trace_dsc.h"
#include "utilc.h"
#include <errno.h>
/* Macros. */
#define OPEN_DATA "FT: " /* Open request for data */
#define OPEN_MSG "FT:MSG " /* Open request for message */
#define END_TRANSFER "TRANS03" /* Message for xfer complete */
/* Typedefs. */
struct data_buffer {
char sf_length[2]; /* SF length = 0x0023 */
char sf_d0; /* 0xD0 */
char sf_request_type[2]; /* request type */
char compress_indic[2]; /* 0xc080 */
char begin_data; /* 0x61 */
char data_length[2]; /* Data Length in 3270 byte order+5 */
char data[256]; /* The actual data */
};
struct open_buffer { /* Buffer passed in open request */
char sf_request_type[2]; /* 0x0012 for open request */
char fixed_parms[6]; /* Doc says 010601010403 */
char func_required[10]; /* Doc says 0a0a0000000011010100 */
char data_not_compr[5]; /* Doc says 50055203f0 */
char hdr_length[2]; /* 0x0309 */
char name[7]; /* ft: or ft:msg */
};
struct error_response { /* Buffer to build for an error resp. */
char sf_length[2]; /* 0009 */
char sf_d0; /* 0xd0 */
char sf_tt; /* tt = 00,47,45,46 */
char sf_08; /* 0x08 */
char sf_err_hdr[2]; /* 0x6904 */
char sf_err_code[2]; /* The error code */
};
#define UPLOAD_LENGTH 2048-2
struct upload_buffer_hdr {
char sf_length[2]; /* SF length */
char sf_d0; /* 0xd0 */
char sf_request_type[2]; /* 0x4605 */
char sf_recnum_hdr[2]; /* 0x6306 */
char sf_recnum[4]; /* record number in host byte order */
char sf_compr_indic[2]; /* 0xc080 */
char sf_begin_data; /* 0x61 */
char sf_data_length[2]; /* Data length */
};
struct upload_buffer {
struct upload_buffer_hdr header; /* The header */
/* The actual data */
char sf_data[UPLOAD_LENGTH - sizeof(struct upload_buffer_hdr)];
};
/* Statics. */
static Boolean message_flag = False; /* Open Request for msg received */
static int eof;
static unsigned long recnum;
static char *abort_string = CN;
static void dft_abort(const char *s, unsigned short code);
static void dft_close_request(void);
static void dft_data_insert(struct data_buffer *data_bufr);
static void dft_get_request(void);
static void dft_insert_request(void);
static void dft_open_request(struct open_buffer *open_buf);
static void dft_set_cur_req(void);
static int filter_len(char *s, register int len);
/* Process a Transfer Data structured field from the host. */
void
ft_dft_data(unsigned char *data, int length unused)
{
struct data_buffer *data_bufr = (struct data_buffer *)data;
unsigned short data_type;
unsigned char *cp;
if (ft_state == FT_NONE) {
trace_ds(" (no transfer in progress)\n");
return;
}
/* Position to character after the d0. */
cp = (unsigned char *)(data_bufr->sf_request_type);
/* Get the function type */
GET16(data_type, cp);
/* Handle the requests */
switch (data_type) {
case TR_OPEN_REQ:
dft_open_request((struct open_buffer *)cp);
break;
case TR_INSERT_REQ: /* Insert Request */
dft_insert_request();
break;
case TR_DATA_INSERT:
dft_data_insert(data_bufr);
break;
case TR_SET_CUR_REQ:
dft_set_cur_req();
break;
case TR_GET_REQ:
dft_get_request();
break;
case TR_CLOSE_REQ:
dft_close_request();
break;
default:
trace_ds(" Unsupported(0x%04x)\n", data_type);
break;
}
}
/* Process an Open request. */
static void
dft_open_request(struct open_buffer *open_buf)
{
trace_ds(" Open %*.*s\n", 7, 7, open_buf->name);
if (memcmp(open_buf->name, OPEN_MSG, 7) == 0 )
message_flag = True;
else {
message_flag = False;
ft_running(False);
}
eof = False;
recnum = 1;
trace_ds("> WriteStructuredField FileTransferData OpenAck\n");
obptr = obuf;
space3270out(6);
*obptr++ = AID_SF;
SET16(obptr, 5);
*obptr++ = SF_TRANSFER_DATA;
SET16(obptr, 9);
net_output();
}
/* Process an Insert request. */
static void
dft_insert_request(void)
{
trace_ds(" Insert\n");
/* Doesn't currently do anything. */
}
/* Process a Data Insert request. */
static void
dft_data_insert(struct data_buffer *data_bufr)
{
/* Received a data buffer, get the length and process it */
int my_length;
unsigned char *cp;
trace_ds(" Data\n");
if (!message_flag && ft_state == FT_ABORT_WAIT) {
dft_abort(get_message("ftUserCancel"), TR_DATA_INSERT);
return;
}
cp = (unsigned char *) (data_bufr->data_length);
/* Get the data length in native format. */
GET16(my_length, cp);
/* Adjust for 5 extra count */
my_length -= 5;
/*
* First, check to see if we have message data or file data.
* Message data will result in a popup.
*/
if (message_flag) {
/* Data is from a message */
unsigned char *msgp;
unsigned char *dollarp;
/* Get storage to copy the message. */
msgp = (unsigned char *)Malloc(my_length + 1);
/* Copy the message. */
memcpy(msgp, data_bufr->data, my_length);
/* Null terminate the string. */
dollarp = (unsigned char *)memchr(msgp, '$', my_length);
if (dollarp != NULL)
*dollarp = '\0';
else
*(msgp + my_length) = '\0';
/* If transfer completed ok, use our msg. */
if (memcmp(msgp, END_TRANSFER, strlen(END_TRANSFER)) == 0) {
Free(msgp);
ft_complete((String)NULL);
} else if (ft_state == FT_ABORT_SENT && abort_string != CN) {
Free(msgp);
ft_complete(abort_string);
Free(abort_string);
abort_string = CN;
} else {
ft_complete((char *)msgp);
Free(msgp);
}
} else if (my_length > 0) {
/* Write the data out to the file. */
int rv = 1;
if (ascii_flag && remap_flag) {
/* Filter. */
unsigned char *s = (unsigned char *)data_bufr->data;
unsigned len = my_length;
while (len--) {
*s = ft2asc[*s];
s++;
}
}
if (ascii_flag && cr_flag) {
char *s = (char *)data_bufr->data;
unsigned len = my_length;
/* Delete CRs and ^Zs. */
while (len) {
unsigned l = filter_len(s, len);
if (l) {
rv = fwrite(s, l, (size_t)1,
ft_local_file);
if (rv == 0)
break;
ft_length += l;
}
if (l < len)
l++;
s += l;
len -= l;
}
} else {
rv = fwrite((char *)data_bufr->data, my_length,
(size_t)1, ft_local_file);
ft_length += my_length;
}
if (!rv) {
/* write failed */
char *buf;
buf = xs_buffer("write(%s): %s", ft_local_filename,
strerror(errno));
dft_abort(buf, TR_DATA_INSERT);
Free(buf);
}
/* Add up amount transferred. */
ft_update_length();
}
/* Send an acknowledgement frame back. */
trace_ds("> WriteStructuredField FileTransferData DataAck(%lu)\n",
recnum);
obptr = obuf;
space3270out(12);
*obptr++ = AID_SF;
SET16(obptr, 11);
*obptr++ = SF_TRANSFER_DATA;
SET16(obptr, TR_NORMAL_REPLY);
SET16(obptr, TR_RECNUM_HDR);
SET32(obptr, recnum);
recnum++;
net_output();
}
/* Process a Set Cursor request. */
static void
dft_set_cur_req(void)
{
trace_ds(" SetCursor\n");
/* Currently doesn't do anything. */
}
/* Process a Get request. */
static void
dft_get_request(void)
{
int numbytes;
size_t numread;
unsigned char *bufptr;
struct upload_buffer *upbufp;
trace_ds(" Get\n");
if (!message_flag && ft_state == FT_ABORT_WAIT) {
dft_abort(get_message("ftUserCancel"), TR_GET_REQ);
return;
}
/*
* This is a request to send an upload buffer.
* First check to see if we are finished (eof = True).
*/
if (eof) {
/* We are done, send back the eof error. */
trace_ds("> WriteStructuredField FileTransferData EOF\n");
space3270out(sizeof(struct error_response) + 1);
obptr = obuf;
*obptr++ = AID_SF;
SET16(obptr, sizeof(struct error_response));
*obptr++ = SF_TRANSFER_DATA;
*obptr++ = HIGH8(TR_GET_REQ);
*obptr++ = TR_ERROR_REPLY;
SET16(obptr, TR_ERROR_HDR);
SET16(obptr, TR_ERR_EOF);
} else {
trace_ds("> WriteStructuredField FileTransferData Data(%lu)\n",
recnum);
space3270out(sizeof(struct upload_buffer) + 1);
obptr = obuf;
*obptr++ = AID_SF;
/* Set buffer pointer */
upbufp = (struct upload_buffer *) obptr;
/* Skip length for now */
obptr += 2;
*obptr++ = SF_TRANSFER_DATA;
SET16(obptr, TR_GET_REPLY);
SET16(obptr, TR_RECNUM_HDR);
SET32(obptr, recnum);
recnum++;
SET16(obptr, TR_NOT_COMPRESSED);
*obptr++ = TR_BEGIN_DATA;
/* Size of the data buffer */
numbytes = sizeof(upbufp->sf_data);
SET16(obptr, numbytes+5);
bufptr = (unsigned char *)upbufp->sf_data;
obptr = (unsigned char *)upbufp->header.sf_data_length;
while (numbytes > 1) {
/* Continue until we run out of buffer */
if (cr_flag) {
/* Insert CR after LF. */
if (fgets((char *)bufptr, numbytes,
ft_local_file) != CN) {
/* We got a line. */
/* Filter. */
{
unsigned char *s = bufptr;
while (*s) {
*s = asc2ft[*s];
s++;
}
}
/* Decrement left. */
numbytes -= (strlen((char *)bufptr)+1);
/* Point to \r at end of str. */
bufptr += (strlen((char *)bufptr)-1);
if (*bufptr == '\n') {
/* Stick in the \r\n. */
memcpy(bufptr, "\r\n", 2);
}
/* Point to next space. */
bufptr += 2;
if (numbytes == 0) {
/* At end of buffer */
if (*(bufptr - 1) != '\n') {
/*
* If not a LF, Back up
* the buff pointer.
*/
bufptr--;
}
}
}
} else {
/* Not crlf, do binary read. */
numread = fread(bufptr, 1, numbytes,
ft_local_file);
if (ascii_flag && remap_flag) {
unsigned char *s = bufptr;
int i = numread;
while (i) {
*s = asc2ft[*s];
s++;
i--;
}
}
bufptr += numread;
numbytes -= numread;
}
if (feof(ft_local_file)) {
/* End of file. */
/* Set that we are out of data. */
eof = True;
break;
} else if (ferror(ft_local_file)) {
char *buf;
buf = xs_buffer("read(%s): %s",
ft_local_filename,
strerror(errno));
dft_abort(buf, TR_GET_REQ);
}
}
/* Set data length. */
SET16(obptr, bufptr-obptr+4);
/* Accumulate length written. */
ft_length += bufptr-obptr;
/* Send last byte to net_output. */
obptr = bufptr;
}
/* We built a buffer, let's write it back to the mainframe. */
/* Position to beg. of buffer. */
bufptr = obuf;
bufptr++;
/* Set the sf length. */
SET16(bufptr, (obptr-1)-obuf);
net_output();
ft_update_length();
}
/* Process a Close request. */
static void
dft_close_request(void)
{
/*
* Recieved a close request from the system.
* Return a close acknowledgement.
*/
trace_ds(" Close\n");
trace_ds("> WriteStructuredField FileTransferData CloseAck\n");
obptr = obuf;
space3270out(6);
*obptr++ = AID_SF;
SET16(obptr, 5); /* length */
*obptr++ = SF_TRANSFER_DATA;
SET16(obptr, TR_CLOSE_REPLY);
net_output();
}
/* Abort a transfer. */
static void
dft_abort(const char *s, unsigned short code)
{
if (abort_string != CN)
Free(abort_string);
abort_string = NewString(s);
trace_ds("> WriteStructuredField FileTransferData Error\n");
obptr = obuf;
space3270out(10);
*obptr++ = AID_SF;
SET16(obptr, 9); /* length */
*obptr++ = SF_TRANSFER_DATA;
*obptr++ = HIGH8(code);
*obptr++ = TR_ERROR_REPLY;
SET16(obptr, TR_ERROR_HDR);
SET16(obptr, TR_ERR_CMDFAIL);
net_output();
/* Update the pop-up and state. */
ft_aborting();
}
/* Returns the number of bytes in s, limited by len, that aren't CRs or ^Zs. */
static int
filter_len(char *s, register int len)
{
register char *t = s;
while (len && *t != '\r' && *t != 0x1a) {
len--;
t++;
}
return t - s;
}
#endif /*]*/